package com.resifind.www.service.impl;

import com.resifind.www.constant.*;
import com.resifind.www.dao.*;
import com.resifind.www.dao.impl.*;
import com.resifind.www.exception.BaseException;
import com.resifind.www.exception.ClientException;
import com.resifind.www.exception.Resp;
import com.resifind.www.po.*;
import com.resifind.www.po.Record;
import com.resifind.www.service.ClientService;
import com.resifind.www.util.JdbcUtils;

import java.io.IOException;
import java.io.InputStream;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.sql.Connection;
import java.time.LocalDate;
import java.time.temporal.ChronoUnit;
import java.util.List;

/**
 * @author 36069
 */
public class ClientServiceImpl implements ClientService {
    private final ClientDao clientDao = new ClientDaoImpl();
    private final RecordDao recordDao = new RecordDaoImpl();

    @Override
    public Resp<String> updateClient(Client client) {
        Connection conn = null;
        try {
            conn = JdbcUtils.getConn();
            JdbcUtils.beginTransaction(conn);
            boolean updateRealNameResult = true;
            boolean updatePersonalInfoResult = true;
            if (client.getRealName() != null && client.getIdNum() != null) {
                //如果是修改实名信息则更新姓名和身份证号
                if (!client.getRealName().matches(Regex.REAL_NAME) || !client.getIdNum().matches(Regex.ID_NUM)) {
                    throw ClientException.realNameError();
                } else {
                    updateRealNameResult = clientDao.updateRealName(client, conn);
                }
            } else {
                //修改个人信息
                updatePersonalInfoResult = clientDao.updatePersonalInfo(client, conn);
            }
            if (updateRealNameResult && updatePersonalInfoResult) {
                JdbcUtils.commitTransaction(conn);
                return Resp.success("success");
            } else {
                JdbcUtils.rollbackTransaction(conn);
                throw new BaseException(ErrorCode.DB_ERROR);
            }
        } catch (BaseException e) {
            throw e;
        } catch (Exception e) {
            JdbcUtils.rollbackTransaction(conn);
            throw new BaseException(ErrorCode.SERVER_ERROR);
        } finally {
            JdbcUtils.closeConn(conn, null, null);
        }
    }

    @Override
    public Resp<String> recharge(int clientId, double amount) {
        //判断充值金额是否合法
        if (amount <= 0) {
            throw ClientException.rechargeAmountError();
        }
        Connection conn = null;
        try {
            conn = JdbcUtils.getConn();
            JdbcUtils.beginTransaction(conn);
            boolean rechargeResult = clientDao.recharge(clientId, amount, conn);
            if (rechargeResult) {
                JdbcUtils.commitTransaction(conn);
                return Resp.success("success");
            } else {
                JdbcUtils.rollbackTransaction(conn);
                throw new BaseException(ErrorCode.DB_ERROR);
            }
        } catch (BaseException e) {
            throw e;
        } catch (Exception e) {
            JdbcUtils.rollbackTransaction(conn);
            throw new BaseException(ErrorCode.SERVER_ERROR);
        } finally {
            JdbcUtils.closeConn(conn, null, null);
        }
    }

    @Override
    public Resp<SignInBean> querySignIn(int clientId) {
        //查询客户的签到记录
        List<Record> records = recordDao.queryRecordByClientId(clientId);
        int continuousDays = 0;
        //计算连续签到天数
        if (records != null && !records.isEmpty()) {
            continuousDays = calculateContinuousDays(records);
        }
        //查询客户的总签到天数
        int totalDays = recordDao.queryTotalDaysByClientId(clientId);
        //封装SignInBean对象
        SignInBean signInBean = new SignInBean();
        signInBean.setRecord(records);
        signInBean.setContinuousDays(continuousDays);
        signInBean.setTotalDays(totalDays);
        return Resp.success(signInBean);
    }

    @Override
    public int calculateContinuousDays(List<Record> recordList) {
        if (recordList == null || recordList.isEmpty()) {
            return 0;
        }
        LocalDate today = LocalDate.now();
        //获取最近一次签到日期
        LocalDate lastDate = LocalDate.parse(recordList.getFirst().getDate());
        //计算和今天的差距
        long between = ChronoUnit.DAYS.between(lastDate, today);
        //如果差距大于1则连续签到天数为0
        if (between > 1) {
            return 0;
        }
        int continuousDays = 1;
        //遍历签到记录
        for (int i = 1; i < recordList.size(); i++) {
            LocalDate date = LocalDate.parse(recordList.get(i).getDate());
            between = ChronoUnit.DAYS.between(date, lastDate);
            if (between == 1) {
                continuousDays++;
                lastDate = date;
            } else {
                break;
            }
        }
        return continuousDays;
    }

    @Override
    public Resp<String> signIn(int clientId) {
        //判断是否已经签到
        List<Record> records = recordDao.queryRecordByClientId(clientId);
        if (records != null && !records.isEmpty()) {
            LocalDate lastDate = LocalDate.parse(records.getFirst().getDate());
            LocalDate today = LocalDate.now();
            if (lastDate.equals(today)) {
                throw ClientException.alreadySignedIn();
            }
        }
        //查询连续签到天数
        int continuousDays = calculateContinuousDays(records);
        //基础积分
        int bonusCoin = 10;
        //连续7天以上奖励翻倍
        int doubleDays = 7;
        if (continuousDays >= doubleDays) {
            bonusCoin *= 2;
        }
        Connection conn = null;
        try {
            conn = JdbcUtils.getConn();
            JdbcUtils.beginTransaction(conn);
            //添加签到记录
            boolean addRecordResult = recordDao.addRecord(clientId, bonusCoin, conn);
            //更新客户积分
            boolean updateBonusCoinResult = clientDao.updateCoin(clientId, bonusCoin, conn);
            if (addRecordResult && updateBonusCoinResult) {
                JdbcUtils.commitTransaction(conn);
                return Resp.success("success");
            } else {
                JdbcUtils.rollbackTransaction(conn);
                throw new BaseException(ErrorCode.DB_ERROR);
            }
        } catch (BaseException e) {
            throw e;
        } catch (Exception e) {
            JdbcUtils.rollbackTransaction(conn);
            throw new BaseException(ErrorCode.SERVER_ERROR);
        } finally {
            JdbcUtils.closeConn(conn, null, null);
        }
    }

    @Override
    public Resp<String> updateAvatar(int clientId, String fileName, InputStream inputStream) {
        //校验文件格式
        String fileSuffix = fileName.substring(fileName.lastIndexOf(".")).toLowerCase();
        String[] allowedSuffixes = {".jpg", ".jpeg", ".png"};
        boolean allowed = false;
        for (String allowedSuffix : allowedSuffixes) {
            if (fileSuffix.equals(allowedSuffix)) {
                allowed = true;
                break;
            }
        }
        if (!allowed) {
            //异常：文件格式不支持
            throw ClientException.avatarFileFormatError();
        }
        //获取当前时间戳
        long timestamp = System.currentTimeMillis();
        //构建保存文件名
        String saveFileName = clientId + "_" + timestamp + fileSuffix;
        //构建保存路径
        Path savePath = Paths.get(ImgPaths.AVATAR_LOCAL_PATH, saveFileName);
        Path savePathTomcat = Paths.get(ImgPaths.AVATAR_TOMCAT_PATH, saveFileName);
        //将inputStream写到字节数组中
        try {
            byte[] bytes = inputStream.readAllBytes();
            //将字节数组写入文件
            Files.write(savePath, bytes);
            Files.write(savePathTomcat, bytes);
        } catch (IOException e) {
            //异常：上传头像失败
            throw ClientException.avatarUploadError();
        }
        Connection conn = null;
        try {
            conn = JdbcUtils.getConn();
            JdbcUtils.beginTransaction(conn);
            boolean updateAvatarResult = clientDao.updateAvatar(clientId, saveFileName, conn);
            if (updateAvatarResult) {
                String oldAvatar = clientDao.queryClientByClientId(clientId).getAvatar();
                if (oldAvatar != null && !oldAvatar.isEmpty()) {
                    //删除旧头像
                    Path oldPath = Paths.get(ImgPaths.AVATAR_LOCAL_PATH, oldAvatar);
                    Path oldPathTomcat = Paths.get(ImgPaths.AVATAR_TOMCAT_PATH, oldAvatar);
                    if (Files.exists(oldPath) && Files.exists(oldPathTomcat)) {
                        Files.deleteIfExists(oldPath);
                        Files.deleteIfExists(oldPathTomcat);
                    }
                }
                JdbcUtils.commitTransaction(conn);
                return Resp.success(saveFileName);
            } else {
                JdbcUtils.rollbackTransaction(conn);
                throw new BaseException(ErrorCode.DB_ERROR);
            }
        } catch (IOException e) {
            //异常：删除旧头像文件失败
            throw ClientException.avatarFileDeleteError();
        } catch (BaseException e) {
            throw e;
        } catch (Exception e) {
            JdbcUtils.rollbackTransaction(conn);
            throw new BaseException(ErrorCode.SERVER_ERROR);
        } finally {
            JdbcUtils.closeConn(conn, null, null);
        }
    }
}
